﻿using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using Volo.Abp.Application.Services;
using Volo.Abp.Domain.Entities;
using Volo.Abp.Json;
using Volo.Abp.Settings;
using Xms.Abp.Authorization;
using Xms.Abp.Domain.Repositories;
using Xms.Abp.Features;
using Xms.Abp.Identity;
using Xms.Abp.Linq;
using Xms.Abp.ObjectMapping;
using Xms.Abp.OperationLogging;
using Xms.Abp.Settings;

namespace Xms.Abp.Application.Services;

public abstract class XmsApplicationService : ApplicationService
{
    protected IOperationLoggingManager OperationLoggingManage => LazyInject<IOperationLoggingManager>();
    protected IJsonSerializer JsonSerializer => LazyInject<IJsonSerializer>();
    protected new IFeatureChecker FeatureChecker => LazyInject<IFeatureChecker>();
    private IQueryableExecuter _QueryableExecuter;
    protected IQueryableExecuter QueryableExecuter
    {
        get
        {
            if (_QueryableExecuter == null)
            {
                _QueryableExecuter = AsyncExecuter as IQueryableExecuter;
                if (_QueryableExecuter == null)
                {
                    _QueryableExecuter = LazyInject<IQueryableExecuter>();
                }
            }
            return _QueryableExecuter;
        }
    }

    protected new IXmsObjectMapper ObjectMapper => base.ObjectMapper as IXmsObjectMapper;
    protected virtual Dictionary<string, string> Policies { get; }
    protected virtual string GetPolicy([CallerMemberName] string memberName = null)
    {
        memberName = memberName.RemovePostFix("PolicyName").RemovePostFix("Async");
        return Policies.GetOrDefault(memberName);
    }
#pragma warning disable IDE0051 // 删除未使用的私有成员
    private new ISettingProvider SettingProvider => throw new NotSupportedException();
#pragma warning restore IDE0051 // 删除未使用的私有成员
    protected AbpSettings AbpSettings => LazyInject<AbpSettings>();
    public XmsApplicationService()
    {
        var type = this.GetType();
        var attr = type.GetCustomAttribute<PermissionsUseAttribute>();
        if (attr != null)
        {
            Policies = PermissionsConst.ToDictionary(attr.PermissionsConstType);
        }
        else
        {
            Policies = new();
        }
    }

    protected virtual async Task AddOperationLogAsync(string operation, string message, string source, string target, IUser user = null)
    {
        await OperationLoggingManage.AddAsync(operation, message, source, target, user);
    }

    protected virtual async Task AddOperationLogAsync<TData>(string operation, string message, TData source, TData target, IUser user = null)
    {
        await AddOperationLogAsync(operation, message, JsonSerializer.Serialize(source), JsonSerializer.Serialize(target), user);
    }

    protected async Task<bool> IsGrantPolicyAsync(string policyName)
    {
        return await AuthorizationService.IsGrantedAsync(policyName);
    }

    public TService LazyInject<TService>()
    {
        return LazyServiceProvider.LazyGetRequiredService<TService>();
    }

    [Obsolete("Use LazyInject method.")]
    public TService Inject<TService>()
    {
        return ServiceProvider.GetRequiredService<TService>();
    }
}

public abstract class XmsApplicationService<TRepositoryEntity> : XmsApplicationService
    where TRepositoryEntity : Entity
{
    protected IXmsRepository<TRepositoryEntity> Repository { get; }
    public XmsApplicationService(IXmsRepository<TRepositoryEntity> repository)
    {
        Repository = repository;
    }
}

public abstract class XmsApplicationService<TRepositoryEntity, TKey> : XmsApplicationService
    where TRepositoryEntity : Entity<TKey>
{
    protected IXmsRepository<TRepositoryEntity, TKey> Repository { get; }
    public XmsApplicationService(IXmsRepository<TRepositoryEntity, TKey> repository)
    {
        Repository = repository;
    }
}

